home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 680 / sattrack / ifflib20.lzh / ShowIFF / ShowIFF.c < prev    next >
C/C++ Source or Header  |  1991-02-14  |  24KB  |  791 lines

  1. /****************************************************************************
  2. **                                                                         **
  3. **  ShowIFF - a comfortable IFF file viewer for CLI and WorkBench          **
  4. **                               by                                        **
  5. **  Christian A. Weber, Bruggerweg 2, CH-8037 Zürich, Switzerland          **
  6. **                                                                         **
  7. **  For documentation, refer to the file "ShowIFF.doc".                    **
  8. **                                                                         **
  9. **  All known formats (including Overscan, HAM, HalfBrite, SHAM) are       **
  10. **  supported. If a picture is larger than the screen, you may use the     **
  11. **  mouse to scroll around (If you have enough CHIP memory...)             **
  12. **                                                                         **
  13. **  Any suggestions. donations or bug reports are welcome. E-mail to:      **
  14. **  cbmehq!cbmswi!mighty!chris@cbmvax.commodore.com                        **
  15. **                                                                         **
  16. *****************************************************************************
  17. **                                                                         **
  18. **  This program is in the Public Domain. Use it at your own risk.         **
  19. **                                                                         **
  20. **  Requirements:  - arp.library V39+                                      **
  21. **                 - iff.library V19+                                      **
  22. **                                                                         **
  23. **  To compile:    - Lattice C compiler V5.04 or above (use 32bit ints)    **
  24. **                 - The file 'arpstartup.o' (My ARP startup module)       **
  25. **                 - The file 'arpglue.lib' for Printf etc.                **
  26. **                                                                         **
  27. *****************************************************************************
  28. **                                                                         **
  29. **    Modification History:                                                **
  30. **    --------------------                                                 **
  31. **                                                                         **
  32. **    15-Oct-87  CHW  V1.0   Created this file!                            **
  33. **    30-Jun-88  CHW  V1.4   Directory scan fixed for FFS, cleaned up      **
  34. **    16-Nov-88  CHW  V1.5   Overscan implemented                          **
  35. **    28-Nov-88  CHW  V1.6   Minimal screen size is now 64x64 pixels       **
  36. **    02-Jan-89  CHW  V1.7   Double-buffering implemented                  **
  37. **    25-Sep-89  CHW  V2.01  Changed to Lattice C and ARP library          **
  38. **    27-Sep-89  CHW  V2.02  Screen scrolling implemented                  **
  39. **    22-Nov-89  CHW  V2.03  Rejects Non-ILBM files correctly              **
  40. **    21-Feb-90  CHW  V2.04  'NoMemForGfx' bug fixed, overscan fixed       **
  41. **    28-Feb-90  CHW  V2.10  SHAM support code added                       **
  42. **    14-Mar-90  CHW  V2.11  Memory fragmentation workaround, cleanup      **
  43. **    08-Apr-90  CHW  V2.12  Pics with more than 6 planes don't guru       **
  44. **    22-Apr-90  CHW  V2.14  New startup code, WB cleanup works now.       **
  45. **    16-Jul-90  CHW  V2.15  Works now properly with MoreRows & OS 2.0     **
  46. **    16-Sep-90  CHW  V2.16  Scrolling SHAM pictures implemented           **
  47. **    03-Oct-90  CHW  V2.17  MaxX0 divided by 2 because of a 2.0 bug       **
  48. **    30-Oct-90  MAB  V2.20  ShowIFF can be turned into an appicon         **
  49. **    11-Jan-91  CHW  V2.21  SHAM color errors fixed                       **
  50. **    11-Jan-91  CHW  V2.22  AppIcon image/pos are taken from .info file   **
  51. **    13-Jan-91  CHW  V2.23  COMMAND mode added, overscan bug fixed (?)    **
  52. **    14-Jan-91  CHW  V2.24  Icon tooltypes added, code moved around       **
  53. **                                                                         **
  54. ****************************************************************************/
  55.  
  56. #define APPICON_MODE    /* This works only with the 2.0 include files */
  57.  
  58. #include <proto/exec.h>
  59. #include <exec/memory.h>
  60. #include <proto/graphics.h>
  61. #include <proto/intuition.h>
  62. #include <graphics/gfxbase.h>
  63. #include <graphics/gfxmacros.h>
  64. #include <arp/arpbase.h>
  65. #include <libraries/dosextens.h>
  66. #include <hardware/custom.h>
  67. #include <workbench/startup.h>
  68. #include <string.h>
  69. #include <libraries/iff.h>            /* Not an official CBM file (yet?:-) */
  70.  
  71. #ifdef APPICON_MODE
  72. #include <proto/icon.h>
  73. #include <proto/wb.h>
  74. #endif
  75.  
  76. #define MIN(a,b) ((a)<(b)?(a):(b))
  77. #define MAX(a,b) ((a)>(b)?(a):(b))
  78. #define reg register                    /* My favorite alias :-) */
  79.  
  80. #define ARG_PATTERN    0                /* Argument numbers for GADS() */
  81. #define ARG_ALL        1
  82. #define ARG_LOOP       2
  83. #define ARG_DELAY      3
  84. #define ARG_NOBREAK    4
  85. #define ARG_NOOVERSCAN 5
  86. #define ARG_COMMAND    6
  87. #define ARG_INVALID    7
  88.  
  89. #define OPTIONSTOOLTYPE        "OPTIONS"
  90. #define XPOSTOOLTYPE        "ICONXPOS"
  91. #define YPOSTOOLTYPE        "ICONYPOS"
  92. #define ICONNAMETOOLTYPE    "ICONNAME"
  93. #define APPICONPORTNAME        "ShowIFF-AppIcon"
  94. #define DEFAULTAPPICONNAME    "IFF Picture Viewer"
  95.  
  96. #define PICF_DYNA 1
  97.  
  98. /* Externals: */
  99. extern void exit(LONG);                    /* My startup code's exit function */
  100. extern struct Process *ProcessBase;        /* Pointer to our process */
  101. extern struct Library *ArpBase;            /* Also used for DOS functions */
  102. extern struct Custom __far custom;        /* For SHAM/DYNA copper list */
  103. extern BYTE NewOS;                        /* 0 if Kick1.2/1.3, >0 if Kick2.x */
  104.  
  105. /* Globals: */
  106. char WindowTitle[]   = "CON:0/24/640/82/ShowIFF V2.25  24-Jan-91 by Christian A. Weber & Martin A. Blatter ";
  107. char CLI_Template[]  = "Patterns/...,ALL/s,L=LOOP/s,D=DELAY/k,NB=NOBREAK/s,NO=NOOVERSCAN/s,COMMAND/k";
  108. char CLI_Help[]      = "ShowIFF V2.25 24-Jan-91 by Christian A. Weber\n"
  109.                       "Usage: ShowIFF [files or patterns] [ALL] [LOOP] [DELAY delay] [NOBREAK]\n"
  110.                       "\t\t[NOOVERSCAN] [COMMAND \"Command %s args\"]";
  111. char StdWindowName[] = "NIL:";            /* Standard workbench window name */
  112. struct Library *IconBase,*IFFBase;        /* Some libraries we use */
  113. char *argv[ARG_INVALID+1];                /* Arguments, filled in by GADS() */
  114. BPTR wbwindow;                            /* Output window for Workbench mode */
  115. struct DiskObject *dobj;                /* Our icon */
  116. LONG wbdelay=3145728;                    /* keep window open for 3 seconds */
  117. IFFFILE ifffile;                        /* Pointer to our IFF file */
  118. LONG delay=1000000;                        /* Time (in seconds) for each picture */
  119. WORD *emptysprite;                        /* ShowIFF's mouse pointer sprite */
  120.  
  121. struct Picture
  122. {
  123.     struct Screen        *Screen;        /* The picture's screen */
  124.     struct Window        *Window;        /* Window for mouse handling */
  125.     struct BitMap        BitMap;            /* CustomBitMap, can be larger than screen */
  126.     PLANEPTR            MorePlanes[16];    /* Extend bitmap to  24 planes */
  127.     UWORD                *SHAMColors;    /* Ptr to SHAM color table array or NULL */
  128.     WORD                MaxX0,MaxY0;    /* Scrolling limits */
  129.     UWORD                ColorCount;        /* Number of colors in color palette */
  130.     UWORD                ColorTab[256];    /* The picture's color table */
  131.     UBYTE                Flags;
  132. } pic1,pic2;                            /* 2 pictures for double-buffering */
  133.  
  134. struct SHAMChunk
  135. {
  136.     struct Chunk    Chunk;
  137.     UWORD            Version;
  138.     UWORD            Colors[1];            /* open array */
  139. };
  140.  
  141. /***************************************************************************/
  142. /* Free all planes of a bitmap */
  143.  
  144. void FreeBitMap(reg struct BitMap *bm)
  145. {
  146.     reg LONG planesize=bm->BytesPerRow*bm->Rows,i;
  147.  
  148.     for(i=0; i<bm->Depth; ++i)
  149.         if(bm->Planes[i])
  150.         {
  151.             FreeMem(bm->Planes[i],planesize);
  152.             bm->Planes[i]=0;
  153.         }
  154. }
  155.  
  156. /***************************************************************************/
  157. /* Initialize a BitMap structure and allocate CHIP memory for the planes */
  158.  
  159. BOOL AllocBitMap(reg struct BitMap *bm,LONG d,LONG w,LONG h)
  160. {
  161.     reg LONG planesize,i;
  162.  
  163.     InitBitMap(bm,d,w,h);
  164.     planesize=bm->BytesPerRow*bm->Rows;
  165.  
  166.     for(i=0; i<d; ++i)
  167.         if(!(bm->Planes[i]=AllocMem(planesize,MEMF_CHIP|MEMF_CLEAR)))
  168.         {
  169.             FreeBitMap(bm); return FALSE;
  170.         }
  171.     return TRUE;
  172. }
  173.  
  174. /***************************************************************************/
  175. /* Adjust the X/Y position of a screen for correct overscan display */
  176.  
  177. void SetOverscan(reg struct Screen *screen)
  178. {
  179.     reg x=GfxBase->NormalDisplayColumns,y=GfxBase->NormalDisplayRows;
  180.  
  181.     if(!(screen->ViewPort.Modes & HIRES)) x >>= 1;
  182.     if(  screen->ViewPort.Modes & LACE  ) y <<= 1;
  183.  
  184.     x = (x-screen->Width ) >> 1;
  185.     y = (y-screen->Height) >> 1; if(y>0) y=0;
  186.  
  187.     /* Avoid garbled pictures: */
  188.     if(GfxBase->ActiView->DyOffset+y < 0) y = 0-GfxBase->ActiView->DyOffset;
  189.  
  190.     /* Correct overscan HAM color distortions: */
  191.     if(screen->ViewPort.Modes & HAM)
  192.     {
  193.         if(GfxBase->ActiView->DxOffset+x < 96)
  194.             x=96-GfxBase->ActiView->DxOffset;
  195.     }
  196.  
  197. #if 0
  198.     Printf("S(%ld,%ld) O(%ld,%ld) ",screen->Width,screen->Height,x,y);
  199. #endif
  200.  
  201. //    if(NewOS) MoveScreen(screen,x,y);
  202. //    else
  203.     {
  204.         screen->ViewPort.DxOffset = x; screen->ViewPort.DyOffset = y;
  205.         MakeScreen(screen); RethinkDisplay();
  206.     }
  207. }
  208.  
  209. /***************************************************************************/
  210. /* Create intermediate SHAM copper list if this is an SHAM picture */
  211.  
  212. void MakeSHAMCopList(struct Picture *pic)
  213. {
  214.     reg struct UCopList *ucop;
  215.  
  216.     if(!pic->SHAMColors) return;    /* Not an SHAM picture, no work to do */
  217.  
  218.     if(ucop=AllocMem(sizeof(struct UCopList),MEMF_CLEAR))
  219.     {
  220.         reg struct Screen *s=pic->Screen;
  221.         reg LONG i,j,step=(s->ViewPort.Modes&LACE) ? 2:1;
  222.         reg UWORD copx=GfxBase->ActiView->DxOffset+s->Width;
  223.         reg UWORD y0=s->ViewPort.RasInfo->RyOffset;
  224.  
  225.         if(pic->Flags & PICF_DYNA) step=1;
  226.         for(i=1; i<(s->Height/step); ++i)
  227.         {
  228.             CWAIT(ucop,(i-1)*step,(UWORD)((copx>>1)%(UWORD)228))
  229.             for(j=1; j<16; ++j)
  230.                 CMOVE(ucop,custom.color[j],pic->SHAMColors[16*(y0+i)+j])
  231.         }
  232.         CEND(ucop)
  233. //        FreeVPortCopLists(&s->ViewPort);
  234.         s->ViewPort.UCopIns = ucop;
  235.         pic->SHAMColors[16*y0]=pic->ColorTab[0];    /* Fix some weird SHAM pics */
  236.         LoadRGB4(&s->ViewPort,&pic->SHAMColors[16*y0],16);
  237.     }
  238. }
  239.  
  240. /***************************************************************************/
  241. /* Free a picture (that is a window, screen and a custom BitMap) */
  242.  
  243. void ClosePicture(reg struct Picture *pic)
  244. {
  245.     if(pic->Window)
  246.     {
  247.         ScreenToBack(pic->Screen);
  248.         ClearPointer(pic->Window);
  249.         CloseWindow(pic->Window);
  250.         pic->Window=0;
  251.     }
  252.  
  253.     if(pic->Screen)
  254.     {
  255.         CloseScreen(pic->Screen);
  256.         pic->Screen=0;
  257.     }
  258.  
  259.     FreeBitMap(&pic->BitMap);
  260.     RemakeDisplay();    /* remake copperlist to increase MEMF_LARGEST */
  261. }
  262.  
  263. /***************************************************************************/
  264. /* Allocate a picture (Allocate custom BitMap, open screen and window) */
  265.  
  266. BOOL OpenPicture(reg struct Picture *pic,reg struct BitMapHeader *bmhd)
  267. {
  268.     struct NewScreen ns;
  269.     struct NewWindow nw;
  270.  
  271.     ClosePicture(pic);
  272.  
  273.     memset(&ns,0,sizeof(ns));
  274.     memset(&nw,0,sizeof(nw));
  275.     memset(pic,0,sizeof(*pic));
  276.  
  277.     ns.Width        = GfxBase->NormalDisplayColumns;
  278.     ns.Height       = GfxBase->NormalDisplayRows;
  279.     ns.Depth        = MAX(1,bmhd->nPlanes);    if(ns.Depth>6) ns.Depth=4;
  280.     ns.ViewModes    = (UWORD)GetViewModes(ifffile);
  281.     ns.Type         = CUSTOMSCREEN|CUSTOMBITMAP|SCREENQUIET|SCREENBEHIND;
  282.     ns.CustomBitMap = &pic->BitMap;
  283.  
  284.     if(!(ns.ViewModes & HIRES))    { ns.Width  >>= 1; }
  285.     if(  ns.ViewModes & LACE)    { ns.Height <<= 1; }
  286.  
  287.     ns.Width  = MIN(bmhd->w,ns.Width);    ns.Width  = MAX(128,ns.Width);
  288.     ns.Height = MIN(bmhd->h,ns.Height);    ns.Height = MAX(128,ns.Height);
  289.  
  290.     if(!argv[ARG_NOOVERSCAN])
  291.     {
  292.         if((bmhd->w > ns.Width) && (bmhd->w <= (ns.ViewModes&HIRES ? 768:384)))
  293.             ns.Width = bmhd->w;
  294.  
  295.         if((bmhd->h>ns.Height) && (bmhd->h<=(ns.Height+(ns.ViewModes&LACE?80:40))))
  296.             ns.Height = bmhd->h;
  297.     }
  298.  
  299.     if(AllocBitMap(&pic->BitMap,MAX(bmhd->nPlanes,ns.Depth),
  300.                 MAX(bmhd->w,ns.Width),MAX(bmhd->h,ns.Height)))
  301.     {
  302.         reg olddepth      = pic->BitMap.Depth;
  303.         pic->BitMap.Depth = ns.Depth;
  304.         pic->Screen       = OpenScreen(&ns);
  305.         pic->BitMap.Depth = olddepth;
  306.  
  307.         if(nw.Screen=pic->Screen)
  308.         {
  309.             nw.Width      = ns.Width;
  310.             nw.Height     = ns.Height;
  311.             nw.IDCMPFlags = MOUSEBUTTONS|MOUSEMOVE|DELTAMOVE|VANILLAKEY;
  312.             nw.Flags      = BACKDROP|BORDERLESS|ACTIVATE|SIMPLE_REFRESH
  313.                                 |NOCAREREFRESH|REPORTMOUSE|RMBTRAP;
  314.             nw.Type       = CUSTOMSCREEN;
  315.  
  316.             if(pic->Window=OpenWindow(&nw))
  317.             {
  318.                 pic->MaxX0=bmhd->w-ns.Width;
  319.                 if(NewOS && (ns.ViewModes & HIRES))    /* Why is this needed?? */
  320.                      pic->MaxX0 >>= 1;
  321.                 pic->MaxY0=bmhd->h-ns.Height;
  322.  
  323.                 SetPointer(pic->Window,emptysprite,1L,16L,0L,0L);
  324.                 if(bmhd->nPlanes>8)
  325.                 {
  326.                     static UWORD truecoltab[16] =
  327.                     {    0x000,0x00F,0x080,0x08F,0xF00,0xF0F,0xF80,0xF8F,
  328.                         0x000,0x00F,0x0F0,0x0FF,0xF00,0xF0F,0xFF0,0xFFF
  329.                     };
  330.                     memcpy(pic->ColorTab,truecoltab,sizeof(truecoltab));
  331.                     pic->Screen->BitMap.Planes[0]=pic->BitMap.Planes[7];
  332.                     pic->Screen->BitMap.Planes[1]=pic->BitMap.Planes[15];
  333.                     pic->Screen->BitMap.Planes[2]=pic->BitMap.Planes[23];
  334.                     pic->Screen->BitMap.Planes[3]=pic->BitMap.Planes[14];
  335.                     pic->ColorCount=16;
  336.                 }
  337.                 else
  338.                 {
  339.                     if(!(pic->ColorCount=GetColorTab(ifffile,pic->ColorTab)))
  340.                     {
  341.                         /* Provide default colors for pictures without a CMAP */
  342.                         pic->ColorCount=2;
  343.                         pic->ColorTab[0]=0xeca; pic->ColorTab[1]=0x000;
  344.                     }
  345.                 }
  346.  
  347.                 if(pic->ColorCount>32) pic->ColorCount = 32; /* Old DigiView */
  348.                 LoadRGB4(&pic->Screen->ViewPort,pic->ColorTab,pic->ColorCount);
  349.                 SetOverscan(pic->Screen);
  350.                 return TRUE;
  351.             }
  352.         }
  353.     }
  354.     ClosePicture(pic);
  355.     return FALSE;
  356. }
  357.  
  358. /***************************************************************************/
  359. /* Close all resources and exit to CLI/WorkBench */
  360.  
  361. void Fail(reg char *reason)
  362. {
  363.     Puts(reason);
  364.  
  365.     ClosePicture(&pic1); ClosePicture(&pic2);
  366.     if(ifffile)    CloseIFF(ifffile);
  367.     if(dobj)    FreeDiskObject(dobj);
  368.  
  369.     if(wbwindow)
  370.     {
  371.         WaitForChar(wbwindow,wbdelay);    /* Let them see our text */
  372.         Close(wbwindow);
  373.     }
  374.  
  375.     if(IFFBase)        CloseLibrary(IFFBase);
  376.     if(IconBase)    CloseLibrary(IconBase);
  377.  
  378.     exit(0L);    /* Back to the startup code (important for Workbench) */
  379. }
  380.  
  381. /***************************************************************************/
  382. /* That's the big one! Load & display a picture (with mouse-scrolling),
  383.    return FALSE if user presses the RMB (abort), else return TRUE */
  384.  
  385. BOOL ShowPicture(reg char *name)
  386. {
  387.     reg BOOL cont=TRUE;
  388.     reg struct BitMapHeader *bmhd;
  389.  
  390.     if(!strcmp(name+strlen(name)-5,".info")) return TRUE;    /* Skip icons */
  391.     Printf("%s ... ",name);
  392.  
  393.     if(ifffile) CloseIFF(ifffile);
  394.  
  395.     if(!(ifffile=OpenIFF(name)))
  396.     {
  397.         Puts("- not an IFF file!");
  398.         return TRUE;
  399.     }
  400.  
  401.     if(*(((ULONG *)ifffile)+2) != ID_ILBM)
  402.     {
  403.         Puts("- not an ILBM file!");
  404.         return TRUE;
  405.     }
  406.  
  407.     if(!(bmhd=GetBMHD(ifffile)))
  408.     {
  409.         Printf("- Mangled IFF file (Error %ld)\n",IFFError());
  410.         return TRUE;
  411.     }
  412.  
  413.     Printf("%ld x %ld x %ld ",bmhd->w,bmhd->h,bmhd->nPlanes);
  414. retry:
  415.     if(OpenPicture(&pic1,bmhd))
  416.     {
  417.         if(DecodePic(ifffile,&pic1.BitMap))
  418.         {
  419.             reg struct SHAMChunk *sham;
  420.             reg LONG i;
  421.             reg WORD xoff=0,yoff=0;
  422.  
  423.             if(sham=FindChunk(ifffile,ID_SHAM))
  424.             {
  425.                 Printf("SHAM ");
  426.                 if(sham->Version == 0)
  427.                 {
  428.                     pic1.SHAMColors = sham->Colors;
  429.                 }
  430.                 else Printf("Unsupported mode: %ld ",(LONG)sham->Version);
  431.  
  432.                 MakeSHAMCopList(&pic1);
  433.             }
  434.  
  435.             if(sham=FindChunk(ifffile,ID_CTBL))
  436.             {
  437.                 Printf("DYNA ");
  438.                 pic1.SHAMColors = &sham->Version;    /* DYNA has no version */
  439.                 pic1.Flags |= PICF_DYNA;
  440.                 MakeSHAMCopList(&pic1);
  441.             }
  442.  
  443.             ScreenToFront(pic1.Screen);
  444.             ClosePicture(&pic2);
  445.             for(i=delay*50L; i>=0; --i)
  446.             {
  447.                 reg struct IntuiMessage *msg;
  448.  
  449.                 WaitTOF();
  450.                 while(msg=(struct IntuiMessage *)GetMsg(pic1.Window->UserPort))
  451.                 {
  452. newmsg:                switch(msg->Class)
  453.                     {
  454.                     case MOUSEMOVE:
  455.  
  456.                         xoff+=msg->MouseX;
  457.                         yoff+=msg->MouseY;
  458.                         if(xoff>pic1.MaxX0) xoff=pic1.MaxX0;
  459.                         if(xoff<0) xoff=0;
  460.                         if(yoff>pic1.MaxY0) yoff=pic1.MaxY0;
  461.                         if(yoff<0) yoff=0;
  462.                         pic1.Screen->ViewPort.RasInfo->RxOffset=xoff;
  463.                         pic1.Screen->ViewPort.RasInfo->RyOffset=yoff;
  464.                         if(pic1.SHAMColors)
  465.                         {
  466.                             reg struct IntuiMessage *m2;
  467.                             MakeSHAMCopList(&pic1);
  468.                             while(m2=GetMsg(pic1.Window->UserPort))
  469.                             {
  470.                                 ReplyMsg(msg); msg=m2;
  471.                                 if(msg->Class == MOUSEMOVE)
  472.                                 {
  473.                                     xoff+=msg->MouseX;
  474.                                     yoff+=msg->MouseY;
  475.                                 }
  476.                                 else goto newmsg;
  477.                             }
  478.                         }
  479.                         /* ScrollVPort(&pic1.Screen->ViewPort); */
  480.                         MakeScreen(pic1.Screen); RethinkDisplay();
  481.                         break;
  482.  
  483.                     case VANILLAKEY:
  484.                         if(msg->Code == 'c') if(argv[ARG_COMMAND])
  485.                         {
  486.                             char buf[200];
  487.                             SPrintf(buf,argv[ARG_COMMAND],name,name);
  488.                             Execute(buf,NULL,Output());
  489.                         }
  490.                         break;
  491.  
  492.                     case MOUSEBUTTONS:
  493.                         if(!argv[ARG_NOBREAK])
  494.                         {
  495.                             if(msg->Code == MENUDOWN)    goto usrbreak;
  496.                             if(msg->Code == SELECTDOWN)    goto showend;
  497.                         }
  498.                         break;
  499.                     }
  500.                     ReplyMsg(msg);
  501.                 }
  502.                 if(!argv[ARG_NOBREAK]) if(CheckAbort(NULL))
  503.                 {
  504. usrbreak:            Puts("***BREAK"); cont=FALSE; goto showend2;
  505.                 }
  506.             }
  507. showend:    Puts("- Done");
  508. showend2:    pic2=pic1; memset(&pic1,0,sizeof(pic1));
  509.         }
  510.         else
  511.         {
  512.             ClosePicture(&pic1);
  513.             Printf("- Decode error: %ld\n",IFFError());
  514.         }
  515.     }
  516.     else if(pic2.Window)
  517.     {
  518.         ClosePicture(&pic2); goto retry;
  519.     }
  520.     else Puts("- Can't open screen!");
  521.     return cont;
  522. }
  523.  
  524. /***************************************************************************/
  525. /* Expand a pattern and call ShowPicture() for each matching file,
  526.    return FALSE if the user presses ^C or ShowPicture() returns FALSE */
  527.  
  528. BOOL ShowPattern(char *pathname)
  529. {
  530.     char buf[256];
  531.     reg BPTR file;
  532.     reg BOOL cont=TRUE;
  533.  
  534.     if(PreParse(pathname,buf))    /* TRUE if name contains any wildcards */
  535.     {
  536.         reg struct {
  537.             struct AnchorPath APath;
  538.             char   FullPath[255];        /* cheap way to extend ap_Buf[] */
  539.         } *myanchor;
  540. iswild:
  541.         if(myanchor=ArpAlloc(sizeof(*myanchor)))
  542.         {
  543.             reg BOOL showit=TRUE;
  544.             reg LONG error;
  545.  
  546.             myanchor->APath.ap_StrLen = 255;    /* Want full path built */
  547.             myanchor->APath.ap_Flags = APF_DOWILD;
  548.             myanchor->APath.ap_BreakBits=SIGBREAKF_CTRL_C;
  549.  
  550.             error=FindFirst(pathname,&myanchor->APath);
  551.             while(!error)
  552.             {
  553.                 /* +1 because of a lattice bug */
  554.                 if(SetSignal(0L,SIGBREAKF_CTRL_E+1) & SIGBREAKF_CTRL_E)
  555.                 {
  556.                     Puts("***DIR BREAK"); showit=FALSE;
  557.                     /* myanchor->APath.ap_Flags &= ~APF_DODIR; */
  558.                 }
  559.  
  560.                 if(myanchor->APath.ap_Info.fib_DirEntryType>=0)    /* Dir */
  561.                 {
  562.                     if(argv[ARG_ALL])
  563.                     {
  564.                         if(!(myanchor->APath.ap_Flags & APF_DIDDIR))
  565.                         {
  566.                             myanchor->APath.ap_Flags |= APF_DODIR;
  567.                             showit=TRUE;
  568.                         }
  569.                         myanchor->APath.ap_Flags &= ~APF_DIDDIR;
  570.                     }
  571.                 }
  572.                 else if(showit) if(!ShowPicture(myanchor->APath.ap_Buf))
  573.                 {
  574.                     cont = FALSE; break;
  575.                 }
  576.                 error=FindNext(&myanchor->APath);
  577.             }
  578.  
  579.             FreeAnchorChain(&myanchor->APath);
  580.  
  581.             switch(error)
  582.             {
  583.                 case 0:                            break;
  584.  
  585.                 case ERROR_BREAK:                Puts("***BREAK"); cont=FALSE; break;
  586.  
  587.                 case ERROR_OBJECT_NOT_FOUND:    Puts("File not found."); break;
  588.  
  589.                 case ERROR_BUFFER_OVERFLOW:        Puts("Path too long!"); break;
  590.  
  591.                 case ERROR_NO_MORE_ENTRIES:        break;    /* Normal termination */
  592.  
  593.                 default:    Printf("IO error %ld!\n",error); break;
  594.             }
  595.         }
  596.         else Fail("No mem for anchor!");
  597.     }
  598.     else if(file=Open(pathname,MODE_OLDFILE))    /* Just one file ? */
  599.     {
  600.         Close(file); return ShowPicture(pathname);
  601.     }
  602.     else    /* No wildcards, and not a file: it's a device or a directory */
  603.     {
  604.         strcpy(buf,pathname); TackOn(pathname=buf,"*");
  605.         goto iswild;    /* Not really elegant, but it works */
  606.     }
  607.  
  608.     return cont;
  609. }
  610.  
  611. #ifdef APPICON_MODE
  612. /***************************************************************************/
  613. /* Started without arguments: create or delete our appicon */
  614.  
  615. void AppIconStuff(void)
  616. {
  617.     struct Library *WorkbenchBase;
  618.     struct MsgPort *msgport;
  619.       struct AppIcon *ai;
  620.     struct AppMessage *amsg;
  621.  
  622.     if(!(WorkbenchBase = OpenLibrary(WORKBENCH_NAME,36))) return;
  623.  
  624.     if(msgport=FindPort(APPICONPORTNAME))    /* Already running ? */
  625.     {
  626.         Signal(msgport->mp_SigTask,SIGBREAKF_CTRL_C);    /* Kill it */
  627.     }    
  628.     else if(msgport = CreatePort(APPICONPORTNAME,0)) 
  629.     {
  630.         reg char *tooltype;
  631.         if(tooltype=FindToolType(dobj->do_ToolTypes,XPOSTOOLTYPE))
  632.             dobj->do_CurrentX = Atol(tooltype);
  633.         else
  634.             dobj->do_CurrentX = NO_ICON_POSITION;
  635.  
  636.         if(tooltype=FindToolType(dobj->do_ToolTypes,YPOSTOOLTYPE))
  637.             dobj->do_CurrentY = Atol(tooltype);
  638.         else
  639.             dobj->do_CurrentY = NO_ICON_POSITION;
  640.  
  641.         if(!(tooltype=FindToolType(dobj->do_ToolTypes,ICONNAMETOOLTYPE)))
  642.             tooltype = DEFAULTAPPICONNAME;
  643.  
  644.         if(ai = AddAppIconA(0,0,tooltype,msgport,NULL,dobj,NULL)) 
  645.         {
  646.             while(!(Wait(1L << msgport->mp_SigBit | SIGBREAKF_CTRL_C)
  647.                          & SIGBREAKF_CTRL_C))
  648.             {
  649.                 reg BPTR oldcos;
  650.  
  651.                 if(wbwindow=Open(WindowTitle,MODE_OLDFILE))
  652.                 {
  653.                     oldcos = ProcessBase->pr_COS;
  654.                     ProcessBase->pr_COS = wbwindow;
  655.                 }
  656.  
  657.                 while(amsg = GetMsg(msgport)) 
  658.                 {
  659.                     reg i,cont=TRUE;
  660.                     struct WBArg *arg = amsg->am_ArgList;
  661.                       for(i=0; (i < amsg->am_NumArgs) && cont; i++,arg++)
  662.                       {
  663.                         reg BPTR oldcd=0;
  664.                         if(arg->wa_Lock) oldcd=CurrentDir(arg->wa_Lock);
  665.                         else DisplayBeep(NULL);
  666.                         cont=ShowPattern(arg->wa_Name&&*arg->wa_Name ? arg->wa_Name:"*");
  667.                         if(oldcd) CurrentDir(oldcd);
  668.                     }
  669.                     ReplyMsg(amsg);
  670.                 }
  671.                 ClosePicture(&pic2);         /* Close last screen */
  672.                 if(wbwindow)
  673.                 {
  674.                     WaitForChar(wbwindow,2097152);    /* Wait 2 seconds */
  675.                     ProcessBase->pr_COS = oldcos;
  676.                     Close(wbwindow); wbwindow=0;
  677.                     SetSignal(0,SIGBREAKF_CTRL_C);    /* Clear break sig */
  678.                 }
  679.             }
  680.             RemoveAppIcon(ai);
  681.         }
  682.  
  683.         /* Make sure there are no more messages pending */
  684.         while(amsg = GetMsg(msgport)) ReplyMsg(amsg);
  685.         DeletePort(msgport);
  686.     }
  687.     CloseLibrary(WorkbenchBase);
  688. }
  689. #endif
  690.  
  691. /***************************************************************************/
  692. /* Main program: parse the command line or WorkBench-args */
  693.  
  694. void ARPMain(LONG arglen,reg char *argline)
  695. {
  696.        if(!(IconBase = OpenLibrary("icon.library",0)))    Fail("No icon.library!");
  697.     if(!(IFFBase  = OpenLibrary(IFFNAME,0L)))        Fail("No iff.library!");
  698.  
  699.     if(IFFBase->lib_Version < IFFVERSION)
  700.         Puts("WARNING: you have an old version of iff.library!");
  701.  
  702.     emptysprite=ArpAllocMem(20L,MEMF_CHIP|MEMF_CLEAR);
  703.  
  704.     if(arglen)        /* From CLI */
  705.     {
  706.         if(*argline != '\n')
  707.         {
  708.             if(GADS(argline,strlen(argline),CLI_Help,argv,CLI_Template)>0)
  709.             {
  710.                 if(argv[ARG_DELAY]) delay=Atol(argv[ARG_DELAY]);
  711.                 do
  712.                 {
  713.                     reg char **pattern=(char **)argv[ARG_PATTERN];
  714.                     if(*pattern)
  715.                     {
  716.                         while(*pattern) if(!ShowPattern(*pattern++)) goto done;
  717.                     }
  718.                     else ShowPattern("*");
  719.                 } while(argv[ARG_LOOP]);
  720. done: ;
  721.             }
  722.             else Fail(CLI_Help);
  723.         }
  724.         else Fail(CLI_Help);
  725.     }
  726.     else    /* Called from Workbench */
  727.     {
  728.         reg struct WBStartup *startup = (struct WBStartup *)argline;
  729.  
  730.         argv[ARG_ALL]        = (void *)TRUE;            /* Set defaults */
  731. //        argv[ARG_LOOP]       = (void *)FALSE;
  732. //        argv[ARG_NOBREAK]    = (void *)FALSE;
  733. //        argv[ARG_NOOVERSCAN] = (void *)FALSE;
  734.  
  735.         if(dobj = GetDiskObject("ShowIFF"))
  736.         {
  737.             reg char *tooltype;
  738.             if(tooltype=FindToolType(dobj->do_ToolTypes,OPTIONSTOOLTYPE))
  739.             {
  740.                 GADS(tooltype,strlen(tooltype),NULL,argv,CLI_Template);
  741.                 if(argv[ARG_DELAY]) delay=Atol(argv[ARG_DELAY]);
  742.             }
  743.         }
  744.         if(startup->sm_NumArgs > 1)    /* Started with some arguments */
  745.         {
  746.             reg i;
  747.             struct WBArg *arg = startup->sm_ArgList;
  748.  
  749.             if(wbwindow=Open(WindowTitle,MODE_OLDFILE))        /* Open window */
  750.                 ProcessBase->pr_COS=wbwindow;
  751.  
  752.             for(i=1; i<startup->sm_NumArgs; ++i)
  753.             {
  754.                 arg++;
  755.                 if(arg->wa_Lock) CurrentDir(arg->wa_Lock);
  756.                 else Puts("Can't lock dir!");
  757.                 if(arg->wa_Name && *arg->wa_Name)
  758.                 {
  759.                     if(!ShowPattern(arg->wa_Name)) break;
  760.                 }
  761.                 else ShowPattern("*");
  762.             }
  763.         }
  764.         else    /* no arguments, just clicked */
  765. #ifdef APPICON_MODE
  766.         if(NewOS) AppIconStuff(); else
  767. #endif
  768.         {
  769.             if(wbwindow=Open(WindowTitle,MODE_OLDFILE))        /* Open window */
  770.                 ProcessBase->pr_COS=wbwindow;
  771.  
  772.             wbdelay=6291456;    /* 6 seconds delay */
  773. #ifdef GERMAN
  774.             Fail("Bitte klicken Sie alle gewünschten Bild-Dateien oder Schubladen bei ge-\n"
  775.              "drückter SHIFT-Taste an, klicken Sie danach 2x auf das ShowIFF-Piktogramm.");
  776. #else
  777.             Fail("Please select all drawers and files to view while holding\n"
  778.              "down the SHIFT key, then double-click the ShowIFF icon.");
  779. #endif
  780.         }
  781.     }
  782.     wbdelay=1048576;            /* One second delay */
  783. #ifdef GERMAN
  784.     Fail("Fertig.");
  785. #else
  786.     Fail("All done.");
  787. #endif
  788.  
  789. }
  790.  
  791.